home *** CD-ROM | disk | FTP | other *** search
- #ifdef UNIX
- /*
- * File stolen from WAMPES 921229, modified for compatibility with JNOS and my
- * tastes, and left to sink or swim. Blub! ++bsa
- *
- * The actual structure is much closer to that of JNOS than to WAMPES. The
- * reason is that WAMPES uses these weirdball I/O hooks... We will use the
- * "classic" interface, modified by the use of register_fd(). (Actually, the
- * weirdball I/O hooks are just WAMPES's version of register_fd(). The API
- * for WAMPES is a heck of a lot hairier, though.)
- */
-
- #include "global.h"
- #include "commands.h"
-
- #include <fcntl.h>
- #include <termios.h>
- #include <sys/time.h>
- #include <sys/stat.h>
- #include <signal.h>
-
- #ifdef UNIX_SOCKETS
- /* to prevent calling in "socket.h", "tcp.h", and "sockaddr.h" */
- #define _SOCKET_H
- #define _TCP_H
- #define _SOCKADDR_H
- /*lint -save -e508 -e631 -e532 -e27 -e43 */
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <netdb.h>
- /*lint -restore */
- #endif
-
- #include "mbuf.h"
- #include "proc.h"
- /*lint -save -e114 */
- #include "iface.h"
- /*lint -restore */
- #include "asy.h"
- #include "unixasy.h"
- /*lint -esym(762,select) */
- #include "hardware.h"
- #include "devparam.h"
- #include "kisspoll.h"
-
- #if !defined(_lint)
- static char rcsid[] OPTIONAL = "$Id: unixasy.c,v 1.34 1997/09/07 00:31:16 root Exp root $";
- #endif
-
- #ifndef EWOULDBLOCK
- #define EWOULDBLOCK EAGAIN
- #endif
-
- #ifndef TNOS_CRTSCTS
- #define CRTSCTS 0x80000000UL
- #endif
-
- char const *LOCKDIR = NULLCHAR;
-
- static int find_speed (long speed);
- static void asy_tx (int, void *, void *);
- static void asy_input (int, void *, void *);
- static int asy_vmin (int dev, long pktsize);
- static int asy_rts (int dev, unsigned long onoff);
- void pasy (struct asy *asyp);
-
- struct asy *Asy; /* allocated in main.c */
-
- /*---------------------------------------------------------------------------*/
-
- static int dorxqueue (int argc, char **argv, void *p);
- static int dotxqueue (int argc, char **argv, void *p);
- static int dobufsize (int argc, char **argv, void *p);
- static int doasy2stat (int argc, char **argv, void *p);
-
- static struct cmds AsyPcmds[] =
- {
- { "rxqueue", dorxqueue, 0, 0, NULLCHAR },
- { "txqueue", dotxqueue, 0, 0, NULLCHAR },
- { "bufsize", dobufsize, 0, 0, NULLCHAR },
- { "status", doasy2stat, 0, 0, NULLCHAR },
- { NULLCHAR, NULL, 0, 0, NULLCHAR }
- };
-
- /*---------------------------------------------------------------------------*/
-
- static struct {
- long speed;
- speed_t flags;
- } speed_table[] = {
- #ifdef B50
- { 50, B50 },
- #endif
- #ifdef B75
- { 75, B75 },
- #endif
- #ifdef B110
- { 110, B110 },
- #endif
- #ifdef B134
- { 134, B134 },
- #endif
- #ifdef B150
- { 150, B150 },
- #endif
- #ifdef B200
- { 200, B200 },
- #endif
- #ifdef B300
- { 300, B300 },
- #endif
- #ifdef B600
- { 600, B600 },
- #endif
- #ifdef B900
- { 900, B900 },
- #endif
- #ifdef B1200
- { 1200, B1200 },
- #endif
- #ifdef B1800
- { 1800, B1800 },
- #endif
- #ifdef B2400
- { 2400, B2400 },
- #endif
- #ifdef B3600
- { 3600, B3600 },
- #endif
- #ifdef B4800
- { 4800, B4800 },
- #endif
- #ifdef B7200
- { 7200, B7200 },
- #endif
- #ifdef B9600
- { 9600, B9600 },
- #endif
- #ifdef B19200
- { 19200, B19200 },
- #endif
- #ifdef B38400
- { 38400, B38400 },
- #endif
- #ifdef B57600
- { 57600, B57600 },
- #endif
- #ifdef B115200
- { 115200, B115200 },
- #endif
- #ifdef B230400
- { 230400, B230400 },
- #endif
- #ifdef B460800
- { 460800, B460800 },
- #endif
- { -1, 0 }
- };
-
-
- /*---------------------------------------------------------------------------*/
-
- static int
- find_speed (long speed)
- {
- int i;
-
- i = 0;
- while (speed_table[i].speed < speed && speed_table[i + 1].speed > 0)
- i++;
- return i;
- }
-
-
- /*---------------------------------------------------------------------------*/
-
-
- int
- Unixlockfile (char const *name, int dev, char const *basename, int silent)
- {
- int k;
- int fd;
- int (*pf) (const char *fmt,...);
- #ifdef HAVE_BINARY_LOCKFILES
- int pid;
- #else
- char filename[80];
- #endif
-
- pf = (dev) ? tprintf : printf;
- for (k = 0; k < 30; k++) {
- if ((fd = open (name, O_WRONLY | O_CREAT | O_EXCL, 0644)) != -1 || errno != EEXIST)
- break;
- /* read pid, unlink and retry if proc no longer exists */
- if ((fd = open (name, O_RDONLY)) == -1) {
- (void) sleep (1);
- continue; /* timing is everything */
- }
- #ifdef HAVE_BINARY_LOCKFILES
- read (fd, &pid, sizeof (pid));
- close (fd);
- fd = pid;
- #else
- filename[read (fd, filename, 10)] = '\0';
- close (fd);
- sscanf (filename, "%d", &fd);
- #endif
- if (kill (fd, 0) == -1 && errno == ESRCH) {
- if (!silent)
- (void) (*pf) ("Removing stale lockfile for %s\n", basename);
- unlink (name);
- continue;
- }
- (void) (*pf) ("%s%s is locked by process %d\n", (dev) ? "/dev/" : "", basename, fd);
- return -1;
- }
- if (fd == -1) {
- (void) (*pf) ("Can't lock %s%s: %s\n", (dev) ? "/dev/" : "", basename, strerror (errno));
- return -1;
- }
- (void) chmod (name, 0644); /* beware of overly restrictive umask */
- #ifdef HAVE_BINARY_LOCKFILES
- pid = getpid ();
- write (fd, &pid, sizeof (pid));
- #else
- sprintf (filename, "%10d\n", (int)getpid ());
- write (fd, filename, 11);
- #endif
- close (fd);
-
- return 0;
- }
-
-
-
- /*---------------------------------------------------------------------------*/
-
- static char const *lockdir_paths[] = {
- "/usr/spool/uucp",
- "/var/spool/lock",
- "/var/spool/uucp",
- "/var/lock",
- NULLCHAR
- };
-
-
- void
- findUnixLockdir (char *where)
- {
- int k;
- struct stat sb;
-
- if (where && !stat (where, &sb) && S_ISDIR(sb.st_mode)) {
- LOCKDIR = strdup (where);
- return;
- }
-
- for (k = 0; lockdir_paths[k] != NULLCHAR; k++) {
- if (stat (lockdir_paths[k], &sb))
- continue;
- if (S_ISDIR(sb.st_mode)) {
- LOCKDIR = lockdir_paths[k];
- return;
- }
- }
-
- /* error! can't find lockdir! */
- printf ("\007!! Cannot start TNOS!\nCannot locate a directory for the Lockfiles!\nThe following were searched:\n");
- for (k = 0; lockdir_paths[k] != NULLCHAR; k++)
- printf ("\t%s\n", lockdir_paths[k]);
-
- (void) fflush (stdout);
- (void) sleep (5);
- exit (1);
- }
-
-
-
- /*---------------------------------------------------------------------------*/
-
- /* Initialize asynch port "dev" */
- int
- asy_init (dev, ifp, arg1, arg2, bufsize, trigchar, monitor, speed, force, triglevel, polled)
- int dev;
- struct iface *ifp;
- char *arg1; /* Attach args for address and vector */
- char *arg2 OPTIONAL;
- int16 bufsize;
- int trigchar OPTIONAL;
- char monitor OPTIONAL;
- long speed;
- int force OPTIONAL;
- int triglevel;
- int polled OPTIONAL;
- {
- register struct asy *ap;
- char filename[80];
- char *ifn;
- int sp, fd = 0;
- struct termios termios;
- #ifdef POLLEDKISS
- long interval;
- #endif
-
- ap = &Asy[dev];
-
- filename[0] = 0;
- #ifdef UNIX_SOCKETS
- if (atoi (arg2)) {
- struct sockaddr_in addr;
- struct hostent *hp;
- u_long hostaddr;
-
- if ((fd = socket (AF_INET, SOCK_STREAM, 0)) < 0)
- goto Fail;
-
- #if 1
- hostaddr = inet_addr (arg1);
- if (hostaddr != (u_long) - 1) {
- addr.sin_addr.s_addr = hostaddr;
- #else
- if (isaddr (arg1)) {
- *((int32 *) & addr.sin_addr) = aton (arg1);
- #endif
- addr.sin_family = AF_INET;
- } else {
- if ((hp = gethostbyname (arg1)) != NULL) {
- addr.sin_family = (short) hp->h_addrtype;
- #if defined(h_addr)
- memcpy ((caddr_t) & addr.sin_addr, hp->h_addr_list[0], (unsigned) hp->h_length);
- #else
- memcpy ((caddr_t) & addr.sin_addr, hp->h_addr, (unsigned) hp->h_length);
- #endif
- } else {
- tprintf ("unknown host: %s\n", arg1);
- goto Fail;
- }
- }
-
- addr.sin_port = htons ((int16)atoi (arg2));
-
- if (connect (fd, (struct sockaddr *) &addr, sizeof (addr)) < 0)
- goto Fail;
-
- ap->uulock[0] = '\0';
- ap->fd = fd;
-
- } else {
- #endif
- /* just in case the user forgot to create the lock dir */
- (void) mkdir (LOCKDIR, 0777);
- /* UUCP locking with ASCII pid */
- sprintf (ap->uulock, "%s/LCK..%s", LOCKDIR, arg1);
- if (Unixlockfile (ap->uulock, 1, arg1, 0) == -1)
- goto Fail;
- strcpy (filename, "/dev/");
- strcat (filename, arg1);
- if ((fd = open (filename, O_RDWR | O_NONBLOCK | O_NOCTTY, 0644)) == -1) {
- tprintf ("Can't open port: %s\n", strerror (errno));
- goto Fail;
- }
- #ifdef UNIX_SOCKETS
- }
- #endif
- ap->flags = 0;
- ap->iface = ifp;
- sp = find_speed (speed);
- ap->speed = speed_table[sp].speed;
- #ifdef UNIX_SOCKETS
- if (!atoi (arg2)) { /* it's not efficient to do this twice...bfd */
- #endif
- memset ((char *) &termios, 0, sizeof (termios));
- termios.c_iflag = IGNBRK | IGNPAR;
- termios.c_cflag = CS8 | CREAD | CLOCAL | speed_table[sp].flags;
- termios.c_cc[VTIME] = 2;
- ap->pktsize = triglevel & 255;
- if (ap->pktsize)
- termios.c_cc[VMIN] = triglevel & 255;
- if (cfsetispeed (&termios, speed_table[sp].flags) == -1) {
- tprintf ("Can't set speed: %s\n", strerror (errno));
- goto Fail;
- }
- if (cfsetospeed (&termios, speed_table[sp].flags) == -1) {
- tprintf ("Can't set speed: %s\n", strerror (errno));
- goto Fail;
- }
- if (tcsetattr (fd, TCSANOW, &termios) == -1) {
- tprintf ("warning: Can't configure port: %s\n", strerror (errno));
- /* goto Fail; *//* made this non-terminal for z8530 kernel driver */
- }
- /* security: port won't work until re-opened */
- if (filename[0]) {
- if ((ap->fd = open (filename, O_RDWR | O_NONBLOCK | O_NOCTTY, 0644)) == -1) {
- tprintf ("Can't reopen port: %s\n", strerror (errno));
- goto Fail;
- }
- close (fd);
- }
-
- #ifdef UNIX_SOCKETS
- }
- #endif
- /* new asy parameters, defaulted for now */
- ap->rxq = 1; /* disable queueing */
- ap->txq = 1;
- ap->rxbuf = bufsize;
- #ifdef POLLEDKISS
- ap->poller = NULL;
- #endif
-
- /* clear statistics */
- ap->rxints = 0;
- ap->txints = 0;
- ap->rxchar = 0;
- ap->txchar = 0;
- ap->rxput = 0;
- ap->rxovq = 0;
- ap->rxblock = 0;
- ap->txget = 0;
- ap->txovq = 0;
- ap->txblock = 0;
-
- ifp->txproc = newproc (ifn = if_name (ifp, " tx"),
- 256, asy_tx, dev, ifp, NULL, 0);
- free (ifn);
- ap->rxproc = newproc (ifn = if_name (ifp, " hw"),
- 256, asy_input, dev, ifp, NULL, 0);
- free (ifn);
-
- ifp->txproc->ptype = ap->rxproc->ptype = PTYPE_IO;
- register_io (ap->fd, &ap->fd);
-
- #ifdef POLLEDKISS
- if (polled) {
- /* Calculate the poll interval: some processing time +
- * the packet duration for a mtu size packet.
- */
- interval = (((long) ifp->mtu * 10000L) / speed);
- ap->poller = newproc (ifn = if_name (ifp, " poller"),
- 384, kiss_poller, ifp->xdev, (void *) interval, NULL, 0);
- ap->poller->ptype = PTYPE_IO;
- free (ifn);
- }
- #endif
-
- return 0;
-
- Fail:
- rflush (); /* make sure the message gets out */
- if (fd != -1)
- close (fd);
- /* Unlock port */
- if (ap->uulock[0])
- unlink (ap->uulock);
- ap->uulock[0] = '\0';
- ap->iface = NULLIF;
- return -1;
- }
-
-
- /*---------------------------------------------------------------------------*/
-
- int
- asy_stop (struct iface *ifp)
- {
- register struct asy *ap;
-
- ap = &Asy[ifp->dev];
-
- if (ap->iface == NULLIF)
- return -1; /* Not allocated */
-
- unregister_io (ap->fd);
-
- #ifdef POLLEDKISS
- if (ap->poller)
- killproc (ap->poller);
- #endif
- if (ifp->txproc)
- killproc (ifp->txproc);
- ifp->txproc = 0;
-
- if (ap->rxproc)
- killproc (ap->rxproc);
- ap->rxproc = 0;
-
- ap->iface = NULLIF;
-
- free_q (&ap->sndq);
- close (ap->fd);
-
- free_q (&ap->rcvq);
-
- if (ap->uulock[0])
- unlink (ap->uulock);
- ap->uulock[0] = '\0';
-
- return 0;
- }
-
-
- void
- detach_all_asy ()
- {
- register struct asy *ap;
-
- for (ap = Asy; ap != Asy + ASY_MAX; ap++) {
- if (ap->iface == NULLIF)
- break;
- unregister_io (ap->fd);
- if (ap->iface->txproc)
- killproc (ap->iface->txproc);
- ap->iface->txproc = 0;
- if (ap->rxproc)
- killproc (ap->rxproc);
- ap->rxproc = 0;
- ap->iface = NULLIF;
- free_q (&ap->sndq);
- free_q (&ap->rcvq);
- close (ap->fd);
- if (ap->uulock[0])
- unlink (ap->uulock);
- ap->uulock[0] = '\0';
- }
- }
-
-
- /*---------------------------------------------------------------------------*/
-
- /* Set asynch line speed */
- int
- asy_speed (int dev, long bps)
- {
- struct asy *asyp;
- int sp;
- struct termios termios;
-
- if (bps <= 0 || dev >= ASY_MAX)
- return -1;
- asyp = &Asy[dev];
- if (asyp->iface == NULLIF)
- return -1;
- if (bps == 0)
- return -1;
- sp = find_speed (bps);
- if (tcgetattr (asyp->fd, &termios))
- return -1;
- if (cfsetispeed (&termios, speed_table[sp].flags))
- return -1;
- if (cfsetospeed (&termios, speed_table[sp].flags))
- return -1;
- #if 0 /* was !defined(linux) && !defined(BSD) && !defined(__FreeBSD__) This is obsolete stuff! */
- termios.c_cflag &= ~CBAUD;
- termios.c_cflag |= speed_table[sp].flags;
- #endif
- if (tcsetattr (asyp->fd, TCSANOW, &termios))
- return -1;
- asyp->speed = speed_table[sp].speed;
- return 0;
- }
-
-
- /* Set termios VMIN (packet size) */
- static int
- asy_vmin (int dev, long pktsize)
- {
- struct termios termios;
- struct asy *asyp;
-
- if (pktsize < 0 || pktsize > 255 || dev >= ASY_MAX)
- return -1;
- if ((asyp = &Asy[dev])->iface == NULLIF)
- return -1;
- if (tcgetattr (asyp->fd, &termios))
- return -1;
- termios.c_cc[VMIN] = asyp->pktsize = pktsize & 255;
- if (tcsetattr (asyp->fd, TCSANOW, &termios))
- return -1;
- return 0;
- }
-
-
- /* Set or clear RTS/CTS flow control */
- static int
- asy_rts (int dev, unsigned long onoff)
- {
- struct termios termios;
- struct asy *asyp;
-
- if ((asyp = &Asy[dev])->iface == NULLIF)
- return -1;
- if (tcgetattr (asyp->fd, &termios))
- return -1;
- /*
- * note sense is reversed as per DOS version, except that we default to
- * RTS/CTS being *off* for compatibility with earlier ALPHA versions
- */
- if (onoff) {
- asyp->flags &= ~ASY_RTSCTS;
- termios.c_cflag &= ~((tcflag_t) TNOS_CRTSCTS); /*lint !e40 */
- } else {
- asyp->flags |= ASY_RTSCTS;
- termios.c_cflag |= ((tcflag_t) TNOS_CRTSCTS); /*lint !e40 */
- }
- if (tcsetattr (asyp->fd, TCSANOW, &termios))
- return -1;
- return 0;
- }
-
-
- /*---------------------------------------------------------------------------*/
-
- /* Asynchronous line I/O control */
- int32
- asy_ioctl (struct iface * ifp, int cmd, int set, int32 val)
- {
- struct asy *ap = &Asy[ifp->dev];
-
- switch (cmd) {
- case PARAM_SPEED:
- if (set)
- (void) asy_speed (ifp->dev, val);
- return ap->speed;
- case PARAM_MIN:
- if (set)
- (void) asy_vmin (ifp->dev, val);
- return ap->pktsize;
- case PARAM_RTS:
- if (set)
- (void) asy_rts (ifp->dev, (unsigned long) val);
- return (ap->flags & ASY_RTSCTS) == 0;
- default:
- break;
- }
- return -1;
- }
-
-
- /*---------------------------------------------------------------------------*/
-
- static void
- asy_input (int dev, void *arg1 OPTIONAL, void *arg2 OPTIONAL)
- {
- struct timeval tv;
- struct asy *ap;
- fd_set fds;
- char *buf;
- int i, c;
-
- server_disconnect_io ();
- ap = &Asy[dev];
- for (;;) {
- if (kwait (&ap->fd) != 0)
- return;
- ap->rxints++;
- buf = mallocw (ap->rxbuf);
-
- if (ap->pktsize)
- (void) fcntl (ap->fd, F_SETFL, fcntl (ap->fd, F_GETFL, 0) & ~O_NONBLOCK);
- if ((i = read (ap->fd, buf, ap->rxbuf)) == 0 || (!ap->pktsize && i == -1 && errno == EWOULDBLOCK)) {
- if (ap->pktsize)
- (void) fcntl (ap->fd, F_SETFL, fcntl (ap->fd, F_GETFL, 0) | O_NONBLOCK);
- ap->rxblock++;
- free (buf);
- continue;
- }
-
- if (i == -1) {
- if (errno == EINTR || errno == ECHILD) {
- #if 0
- tprintf ("asy_input(%d): read interrupted, retrying.\n", dev);
- #endif
- continue;
- }
- tprintf ("asy_input(%d): read error %d, shutting down\n", dev,
- errno);
- if (ap->pktsize)
- (void) fcntl (ap->fd, F_SETFL, fcntl (ap->fd, F_GETFL, 0) | O_NONBLOCK);
- free (buf);
- return;
- }
- if ((c = ap->rxq) <= 0)
- c = 1;
- while (i > 0 && c > 0) {
- ap->rxchar += (uint32) i;
- ap->rxput++;
- enqueue (&ap->rcvq, qdata ((unsigned char *) buf, (int16) i));
- c--;
- if (ap->pktsize) {
- /* can't just read to check for data, since it might block */
- #ifndef _lint
- FD_ZERO (&fds);
- FD_SET (ap->fd, &fds);
- #endif
- tv.tv_sec = tv.tv_usec = 0;
- if (select (FD_SETSIZE, &fds, 0, 0, &tv) == 0) {
- i = -1;
- errno = EWOULDBLOCK;
- break;
- }
- }
- i = read (ap->fd, buf, ap->rxbuf);
- }
- free (buf);
- if (i == -1 && (errno == EINTR || errno == ECHILD)) {
- #if 0
- tprintf ("asy_input(%d): read interrupted, retrying.\n", dev);
- #endif
- continue;
- }
- if (i == -1 && errno != EWOULDBLOCK) {
- tprintf ("asy_input(%d): read error %d, shutting down\n", dev,
- errno);
- return;
- }
- if (ap->pktsize)
- (void) fcntl (ap->fd, F_SETFL, fcntl (ap->fd, F_GETFL, 0) | O_NONBLOCK);
- if (c < 1 && ap->rxq > 1)
- ap->rxovq++;
- }
- }
-
-
- int
- get_asy (int dev)
- {
- #if 0
- struct asy *ap;
-
- ap = &Asy[dev];
- if (ap->iface == NULLIF)
- return -1;
- while (!ap->rcvq) {
- if (kwait (&ap->rcvq) != 0)
- return -1; /* may not be dead, e.g. alarm in dialer */
- }
- ap = &Asy[dev];
- return PULLCHAR (&ap->rcvq);
- #else
- if (Asy[dev].iface == NULLIF)
- return -1;
- if (!Asy[dev].rcvq) {
- do {
- if (kwait (&Asy[dev].rcvq) != 0)
- return -1; /* may not be dead, e.g. alarm in dialer */
-
- } while (!Asy[dev].rcvq);
- }
- return PULLCHAR (&Asy[dev].rcvq);
-
- #endif
-
- }
-
-
- /*---------------------------------------------------------------------------*/
-
- void
- pasy (struct asy *asyp)
- {
- tprintf ("%s: %lu bps, ", asyp->iface->name, asyp->speed);
- if (asyp->pktsize)
- tprintf ("packet size %d", asyp->pktsize);
- else
- tputs ("non-blocking");
- tprintf (", RTS/CTS %sabled", (asyp->flags & ASY_RTSCTS ? "en" : "dis"));
- #if 0
- tprintf (", carrier %sabled", (asyp->flags & ASY_CARR ? "en" : "dis"));
- #endif
- tprintf ("\n RX: ints %lu chars %lu puts %lu buf %d rxqueue %d qlen %d ovq "
- "%ld block %ld\n",
- asyp->rxints, asyp->rxchar, asyp->rxput, asyp->rxbuf, asyp->rxq,
- len_q (asyp->rcvq), asyp->rxovq, asyp->rxblock);
- tprintf (" TX: ints %lu gets %lu chars %lu txqueue %d qlen %d ovq %ld "
- "block %ld\n",
- asyp->txints, asyp->txget, asyp->txchar, asyp->txq,
- len_q (asyp->sndq), asyp->txovq, asyp->txblock);
- }
-
-
- /*---------------------------------------------------------------------------*/
-
- /* Serial transmit process, common to all protocols */
-
- /*
- * Yes, this badly needs to be rewritten.
- */
-
- static void
- asy_tx (int dev, void *p1 OPTIONAL, void *p2 OPTIONAL)
- {
- register struct mbuf *bp;
- struct asy *asyp;
- int c, l, off;
-
- server_disconnect_io ();
- asyp = &Asy[dev];
- if ((c = asyp->txq) <= 0)
- c = 1;
- for (;;) {
- while (asyp->sndq == NULLBUF) {
- c = asyp->txq;
- if (!c)
- c = 1;
- if (kwait (&asyp->sndq) != 0)
- return;
- asyp->txints++;
- }
- bp = dequeue (&asyp->sndq);
- asyp->txget++;
- off = 0;
- while (bp != NULLBUF) {
- l = write (asyp->fd, bp->data + off, (size_t) bp->cnt - (int16) off);
- if (l == -1 && (errno == EINTR || errno == ECHILD)) {
- #if 0
- tprintf ("asy_tx(%d): write interrupted, retrying.\n", dev);
- #endif
- continue;
- }
- if (l == -1 && errno != EWOULDBLOCK) {
- tprintf ("asy_tx(%d): write error %d, shutting down\n", dev,
- errno);
- return;
- }
- if (l == -1)
- l = 0;
- asyp->txchar += (uint32) l;
- if (l == bp->cnt - off) {
- bp = free_mbuf (bp);
- off = 0;
- } else {
- asyp->txblock++;
- kwait (NULL);
- off += l;
- }
- }
- if (--c < 1 && asyp->txq > 1) {
- asyp->txovq++;
- kwait (NULL);
- }
- }
- }
-
-
- /*---------------------------------------------------------------------------*/
-
- /* Send a message on the specified serial line */
- int
- asy_send (int dev, struct mbuf *bp)
- {
- struct asy *asyp;
-
- if (dev < 0 || dev >= ASY_MAX) {
- free_p (bp);
- return -1;
- }
- asyp = &Asy[dev];
-
- if (asyp->iface == NULLIF)
- free_p (bp);
- else
- enqueue (&asyp->sndq, bp);
- return 0;
- }
-
-
- /* stub, CD not enabled at present */
-
- int
- carrier_detect (int dev OPTIONAL)
- {
- return 1; /* assume always on, with CLOCAL it is! */
- }
-
-
- /*---------------------------------------------------------------------------*/
-
- int
- doasyconfig (int ac, char **av, void *p OPTIONAL)
- {
- struct iface *ip;
- struct asy *ap;
- int k;
-
- if (ac < 3)
- return 1;
- ip = if_lookup (av[1]);
- if (!ip) {
- tprintf ("Interface %s unknown\n", av[1]);
- return 1;
- }
- for (k = 0, ap = Asy; k < ASY_MAX; ap++) {
- if (ap->iface == ip)
- break;
- }
- if (k == ASY_MAX || !ap) {
- tprintf ("Interface %s not asy\n", av[1]);
- return 1;
- }
- return subcmd (AsyPcmds, ac - 1, av + 1, ap);
- }
-
-
- static int
- doasy2stat (int ac OPTIONAL, char **av OPTIONAL, void *d)
- {
- pasy ((struct asy *) d);
- return 0;
- }
-
-
- static int
- dorxqueue (int ac, char **av, void *d)
- {
- return setint (&((struct asy *) d)->rxq, "Receive queue size", ac, av);
- }
-
-
- static int
- dotxqueue (int ac, char **av, void *d)
- {
- return setint (&((struct asy *) d)->txq, "Transmit queue size", ac, av);
- }
-
-
- static int
- dobufsize (int ac, char **av, void *d)
- {
- return setuns (&((struct asy *) d)->rxbuf, "Receive buffer size", ac, av);
- }
-
- #endif /* UNIX */
-